import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import showCodeMessage from '@/api/code';
import { formatJsonToUrlParams, instanceObject } from '@/utils/format';
import userinfo from '@/store/userinfo';
import nocache from '@/store/nocache';
import i18n from '@/utils/lang';
import { encrypt, decrypt } from '@/utils/aes';

const BASE_PREFIX = import.meta.env.VITE_API_BASEURL;
const SERVER_CHANNELID = import.meta.env.VITE_APP_SERVER_CHANNELID;

// 创建实例
const axiosInstance: AxiosInstance = axios.create({
  // 前缀
  baseURL: BASE_PREFIX,
  // 超时
  timeout: 1000 * 30,
  // 请求头
  headers: {
    'Content-Type': 'application/json',
  },
});

// 请求拦截器
axiosInstance.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // TODO 在这里可以加上想要在请求发送前处理的逻辑
    // TODO 比如 loading 等
    const currentUser:any = userinfo().getUserinfo;
    config.data.channelId = config.data.channelId || SERVER_CHANNELID;
    if(import.meta.env.VITE_APP_ENCRYPTION_DECRYPTION === 'YES'){
      console.log("请求拦截器：", config.url, config.data)
      config.data = {
        data: encrypt(JSON.stringify(config.data)),
      }
    }
    // 设置 access_token
    if(currentUser && currentUser.token){
      config.headers!.Authorization = currentUser!.token.access_token;
    }else{
      Reflect.deleteProperty(config.headers!, "Authorization");
    }
    return config;
  },
  (error: AxiosError) => {
    return Promise.reject(error);
  },
);

const i18nMessage = (response:any) => {
  if(/^code_\d+$/.test(response.data.data)){
    const str = `Message.${response.data.data}`;
    ElMessage.error((i18n.global as any).t(str));
  }else if(/^code_\d+$/.test(response.data.msg)){
    const str = `Message.${response.data.msg}`;
    ElMessage.error((i18n.global as any).t(str));
  }else{
    ElMessage.error(response.data.msg);
  }
}

// 延迟函数
const delayTimeFun = async (t:number) => {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res(true);
    }, t * 1000);
  })
}

// 响应拦截器
axiosInstance.interceptors.response.use(
  async (response: AxiosResponse) => {
    // await delayTimeFun(10000);
    // 如果是字符串则解析字符串
    if(import.meta.env.VITE_APP_ENCRYPTION_DECRYPTION === 'YES' && typeof response.data === 'string'){
      // console.log("响应拦截器：", response)
      response.data = decodeURIComponent(decrypt(response.data));
      response.data = response.data.substring(0, response.data.lastIndexOf("}")+1);
      response.data = JSON.parse(response.data.trim());
    }
    const piniaUserinfo:any = userinfo();
    if (response.status === 200) {
      if(response.data.code === 401){
        // 退出登录
        piniaUserinfo.logout();
        nocache().openLogin();
        i18nMessage(response);
      }else if(response.data.code === 500){
        if(response.data.msg !== 'The operation failure'){
          i18nMessage(response);
        }else{
          return response.data;
        }
      }else{
        // ElMessage.success(response.data.msg);
        return response.data;
      }
    }
    ElMessage.info(JSON.stringify(response.status));
    return response;
  },
  (error: AxiosError) => {
    const { response } = error;
    if (response) {
      ElMessage.error(showCodeMessage(response.status));
      return Promise.reject(response.data);
    }
    ElMessage.warning('网络连接异常,请稍后再试!');
    return Promise.reject(error);
  },
);

const service = {
  get<T = unknown>(url: string, data?: object): Promise<T> {
    return axiosInstance.get(url, { params: data });
  },

  post<T = unknown>(url: string, data?: object): Promise<T> {
    return axiosInstance.post(url, data);
  },

  put<T = unknown>(url: string, data?: object): Promise<T> {
    return axiosInstance.put(url, data);
  },

  delete<T = unknown>(url: string, data?: object): Promise<T> {
    return axiosInstance.delete(url, data);
  },

  upload: (url: string, file: FormData | File) =>
    axiosInstance.post(url, file, {
      headers: { 'Content-Type': 'multipart/form-data' },
    }),
  download: (url: string, data: instanceObject) => {
    window.location.href = `${BASE_PREFIX}/${url}?${formatJsonToUrlParams(data)}`;
  },
};

export default service;
